<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>tree</title>
    <script src="js/d3@7.js"></script>
    <!-- <script src="https://cdn.jsdelivr.net/npm/d3@7"></script> -->

</head>

<body>

    <svg width="1000" height="700"></svg>

</body>

<script>

    //数据
    var data = {
        name: "中国",
        children: [
            {
                name: "浙江",
                children: [
                    { name: "杭州", value: 100 },
                    { name: "宁波", value: 100 },
                    { name: "温州", value: 100 },
                    { name: "绍兴", value: 100 }
                ]
            },
            {
                name: "广西",
                children: [
                    {
                        name: "桂林",
                        children: [
                            { name: "秀峰区", value: 100 },
                            { name: "叠彩区", value: 100 },
                            { name: "象山区", value: 100 },
                            { name: "七星区", value: 100 }
                        ]
                    },
                    { name: "南宁", value: 100 },
                    { name: "柳州", value: 100 },
                    { name: "防城港", value: 100 }
                ]
            },
            {
                name: "黑龙江",
                children: [
                    { name: "哈尔滨", value: 100 },
                    { name: "齐齐哈尔", value: 100 },
                    { name: "牡丹江", value: 100 },
                    { name: "大庆", value: 100 }
                ]
            },
            {
                name: "新疆",
                children: [
                    { name: "乌鲁木齐" },
                    { name: "克拉玛依" },
                    { name: "吐鲁番" },
                    { name: "哈密" }
                ]
            }
        ]
    };

    var margin = 60;
    var svg = d3.select("svg");
    var width = svg.attr("width");
    var height = svg.attr("height");

    var g = svg.append("g")
        .attr("transform", "translate(" + margin + "," + margin + ")");


    //创建一个层级布局
    var hierarchyData = d3.hierarchy(data)
        .sum(function (d, i) {
            return d.value;
        });
    //    返回的节点和每一个后代会被附加如下属性:
    //        node.data - 关联的数据，由 constructor 指定.
    //        node.depth - 当前节点的深度, 根节点为 0.
    //        node.height - 当前节点的高度, 叶节点为 0.
    //        node.parent - 当前节点的父节点, 根节点为 null.
    //        node.children - 当前节点的孩子节点(如果有的话); 叶节点为 undefined.
    //        node.value - 当前节点以及 descendants(后代节点) 的总计值; 可以通过 node.sum 和 node.count 计算.
    console.log("🚀 ~ hierarchyData:", hierarchyData)

    //创建一个树状图
    var tree = d3.tree()
        .size([width - 400, height - 200])
        .separation(function (a, b) {
            return (a.parent == b.parent ? 1 : 2) / a.depth;//一种更适合于径向布局的变体，可以按比例缩小半径差距:
        });

    //初始化树状图数据
    var treeData = tree(hierarchyData)
    console.log(treeData);//这里的数据treeData与hierarchyData 相同

    //获取边和节点
    var nodes = treeData.descendants();
    console.log("🚀 ~ nodes:", nodes)
    var links = treeData.links();
    console.log("🚀 ~ links:", links)

    //创建贝塞尔曲线生成器
    var link = d3.linkHorizontal()
        .x(function (d) { return d.y; })//生成的曲线在曲线的终点和起点处的切线是水平方向的
        .y(function (d) { return d.x; });


    //绘制边
    g.append('g')
        .selectAll('path')
        .data(links)
        .enter()
        .append('path')
        .attr('d', function (d, i) {
            var start = { x: d.source.x, y: d.source.y };
            var end = { x: d.target.x, y: d.target.y };
            return link({ source: start, target: end });
        })
        .attr('stroke', 'pink')
        .attr('stroke-width', 1)
        .attr('fill', 'none');


    //创建节点与文字分组
    var gs = g.append('g')
        .selectAll('.g')
        .data(nodes)
        .enter()
        .append('g')
        .attr('transform', function (d, i) {
            return 'translate(' + d.y + ',' + d.x + ')';

        });


    //绘制文字和节点
    gs.append('circle')
        .attr('r', 10)
        .attr('fill', 'blue')
        .attr('stroke-width', 1)
        .attr('stroke', 'pink');


    gs.append('text')
        .attr('x', function (d, i) {
            return d.children ? -85 : 10;//有子元素的话  当前节点的文字前移
        })
        .attr('y', -5)
        .attr('dy', 10)
        .text(function (d, i) {
            return d.data.name + d.value
        })



</script>

</html>